/**
 * 
 */
package com.zufangbao.earth.web.controller.receivable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.demo2do.core.web.resolver.Page;
import com.demo2do.core.web.resolver.Secure;
import com.zufangbao.earth.RoleSpec;
import com.zufangbao.earth.ViewEntry;
import com.zufangbao.earth.entity.contractpartical.ContractPartical;
import com.zufangbao.earth.entity.particalsystem.AppParticles;
import com.zufangbao.earth.entity.security.Principal;
import com.zufangbao.earth.handler.CookieHandler;
import com.zufangbao.earth.handler.ReceivableHandler;
import com.zufangbao.earth.handler.ViewSpecHandler;
import com.zufangbao.earth.service.AppParticlesService;
import com.zufangbao.earth.service.AuthorisedBillSketchService;
import com.zufangbao.earth.service.ContractParticalService;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableConfirmTransactionRecord;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableDeferredPaymentDateBills;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableHistoryToday;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableNotReachPaymentDateBills;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivablePaidOutstanding;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivablePaidToday;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableSummary;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableTransactionRecord;
import com.zufangbao.earth.web.controller.receivable.ReceivableControllerSpec.IReceivableUnClearedToday;
import com.zufangbao.earth.web.interceptor.ViewCategoryValidation;
import com.zufangbao.gluon.api.earth.ReceivablesBrief;
import com.zufangbao.gluon.api.quark.AuthorisedBillSketch;
import com.zufangbao.gluon.api.quark.TransactionRecordSketch;
import com.zufangbao.gluon.exception.CommonException;
import com.zufangbao.gluon.exception.NoAuthorityException;
import com.zufangbao.gluon.exception.InvalidViewCategoryException;
import com.zufangbao.gluon.exception.NoPaymentResourceException;
import com.zufangbao.gluon.exception.NoReceivableHandlerException;
import com.zufangbao.gluon.handler.ResultHandler;
import com.zufangbao.gluon.spec.earth.GlobalSpec4Earth;
import com.zufangbao.gluon.spec.global.GlobalCodeSpec;
import com.zufangbao.gluon.spec.global.GlobalMsgSpec;
import com.zufangbao.sun.entity.order.Order;
import com.zufangbao.sun.entity.receivables.HistoryPaidType;
import com.zufangbao.sun.service.AppService;
import com.zufangbao.sun.service.OrderService;

/**
 * @author wukai
 *
 */
@RequestMapping(ReceivableControllerSpec.NAME)
@Controller
@MenuSetting(ReceivableControllerSpec.MENU_SETTING)
public class ReceivableController {
	
	@Autowired
	@Qualifier("quarkReceivableHandler")
	private ReceivableHandler quarkReceivableHandler;
	
	@Autowired
	@Qualifier("mercuryReceivableHandler")
	private ReceivableHandler mercuryReceivableHandler;
	
	@Autowired
	private CookieHandler cookieHandler;
	
	@Autowired
	private ViewSpecHandler viewSpecHandler;
	
	@Autowired
	private ResultHandler resultHandler;
	
	@Autowired
	private AuthorisedBillSketchService authorisedBillSketchService;
	
	@Autowired
	private AppParticlesService appParticlesService;
	
	@Autowired
	private AppService appService;
	
	@Autowired
	private OrderService orderService;
	
	@Autowired
	private ContractParticalService contractParticalService;
	
	private static Log logger = LogFactory.getLog(ReceivableController.class);
	
	@ViewCategoryValidation
	@RequestMapping(IReceivableSummary.NAME)
	@MenuSetting(IReceivableSummary.SUB_MENU_SETTING)
	public ModelAndView receivablesSummary(HttpServletRequest request,
			   @RequestParam(value = IReceivableSummary.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId, @Secure Principal principal){
		
	try {
		
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			ReceivablesBrief  receivablesBrief = receivableHandler.getReceivablesBrief(appId, particalUniqueId);
			
			int historyPaidBillsCount = receivableHandler.getHistoryPaidOrderCount(appId, particalUniqueId, HistoryPaidType.PAYMENT_ALL);
			
			receivablesBrief.setAppId(appId);
			receivablesBrief.setParticleUniqueId(particalUniqueId);
			receivablesBrief.setPaidHistoryBill(historyPaidBillsCount);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.receivableBriefViewSpec(receivablesBrief, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get receivables brief error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get receivables brief error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get receivables brief error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get receivables brief error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get receivables brief error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	
	@RequestMapping(value = IReceivablePaidToday.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivablePaidToday.SUB_MENU_SETTING)
	public ModelAndView listTodayPaidBills(HttpServletRequest request,
										   @RequestParam(value = IReceivablePaidToday.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
										   Page page, @Secure Principal principal) {
		try {
			
			ViewEntry viewEntry = getAuthorisedViewCategory(request, principal);
			
			String appId = viewEntry.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewEntry);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewEntry);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<AuthorisedBillSketch>  todayPaidBills = receivableHandler.getTodayPaidBill(appId, particalUniqueId, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.todayPaidViewSpec(todayPaidBills, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get today paid bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get today paid bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get today paid bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get today paid bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get today paid bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	
	@RequestMapping(value = IReceivableUnClearedToday.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivableUnClearedToday.SUB_MENU_SETTING)
	public ModelAndView listTodayUnClearedBills(HttpServletRequest request,
										   @RequestParam(value = IReceivableUnClearedToday.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
										   Page page, @Secure Principal principal) {
		
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<AuthorisedBillSketch>  todayUnClearedBills = receivableHandler.getTodayUnpaidOutstandingBill(appId, particalUniqueId, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.todayUnClearedViewSpec(todayUnClearedBills, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get today uncleared bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get today uncleared bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get today uncleared bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get today uncleared bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get today uncleared bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	
	
	@RequestMapping(value = IReceivableHistoryToday.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivableHistoryToday.SUB_MENU_SETTING)
	public ModelAndView listHistoryPaid(HttpServletRequest request,
			@RequestParam(value = IReceivableHistoryToday.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId, 
			@RequestParam(value = GlobalSpec4Earth.PARAM_CONTRACT_NO,required = false,defaultValue = "")String contractNo,
			@RequestParam(value = IReceivableHistoryToday.PARAM_HISTORY_PAID_TYPE,required = false,defaultValue = "0")int historyPaidTypeValue, Page page, @Secure Principal principal) {
		
		try {
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			HistoryPaidType historyPaidType = HistoryPaidType.fromValue(historyPaidTypeValue);
			//TODO not check particleId in new Class;
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<Order> historyPaidOrderList = receivableHandler.getHistoryPaidOrder(appId, particalUniqueId, contractNo, historyPaidType, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.historyPaidViewSpec(historyPaidOrderList, quarkParticles,
					HistoryPaidType.values(),contractNo, 
					historyPaidTypeValue, particalUniqueId, 
					createPrePageContext(request));
			
		}catch(NoReceivableHandlerException e){
			logger.error("get history paid bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(InvalidViewCategoryException e){
			logger.error("get history paid bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get history paid bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get history paid bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	@RequestMapping(value = IReceivablePaidOutstanding.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivablePaidOutstanding.SUB_MENU_SETTING)
	public ModelAndView listOutstandingPaidBills(HttpServletRequest request,
										   @RequestParam(value = IReceivablePaidOutstanding.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
										   Page page, @Secure Principal principal) {
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<AuthorisedBillSketch>  outstandingPaidBills = receivableHandler.getOutstandingBills(appId, particalUniqueId, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.outstandingPaidViewSpec(outstandingPaidBills, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get outstanding bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get outstanding bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get outstanding bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get outstanding bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get outstanding bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	
	@RequestMapping(value = IReceivableTransactionRecord.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivableTransactionRecord.SUB_MENU_SETTING)
	public ModelAndView listTransactionRecord(HttpServletRequest request,
											  @RequestParam(value = IReceivableTransactionRecord.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
											  @Secure Principal principal) {
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			List<ContractPartical> contractParticals = contractParticalService.listAssignContracByUniqueIdAndAppId(particalUniqueId, appId);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			if(CollectionUtils.isEmpty(contractParticals)){
				
				return viewSpecHandler.transactionRecordViewSpec(Collections.EMPTY_LIST, quarkParticles, createPrePageContext(request));
			}
			
			List<Order> orderList = new ArrayList<Order>();
			
			for(ContractPartical contractPartical : contractParticals){
				
				orderList.addAll(orderService.getOrderList(contractPartical.getContract()));
			}
			
			List<String> billIds = authorisedBillSketchService.getUniuqueBillIds(orderList);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			List<TransactionRecordSketch>  transactionRecordSketchs = receivableHandler.getTransactionRecord(appId, particalUniqueId, billIds);
			
			return viewSpecHandler.transactionRecordViewSpec(transactionRecordSketchs, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get transactionRecord bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get transactionRecord bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get transactionRecord bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get transactionRecord bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get transactionRecord bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	@RequestMapping(value = IReceivableConfirmTransactionRecord.NAME,method = RequestMethod.POST)
	@MenuSetting(IReceivableConfirmTransactionRecord.SUB_MENU_SETTING)
	public @ResponseBody String confirmTransactionRecord(HttpServletRequest request,
											  @RequestParam(value = IReceivableConfirmTransactionRecord.PARAM_UNIQUE_PARTICLE_ID)String particalUniqueId,
											  @RequestParam(value = IReceivableConfirmTransactionRecord.PARAM_UNIQUE_TRANSACTION_RECORD_IDS) String uniqueTransactionRecordIdStr,
											  @Secure Principal principal) {
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			List<String> uniqueTransactionRecordIds = JsonUtils.parseArray(uniqueTransactionRecordIdStr, String.class);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			boolean isConfirmSuc = receivableHandler.confirmTransactionRecord(appId, particalUniqueId,uniqueTransactionRecordIds);
			
			if(isConfirmSuc){
				
				return resultHandler.sucJsonResult();
				
			}else{
				
				return resultHandler.errorJsonResult(GlobalSpec4Earth.ErrorMsg4Receivables.MSG_CONFIRM_TRANSACTION_RECORD_FAIL);
			}
			
		}catch(NoReceivableHandlerException e){
			logger.error("get overdue bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return resultHandler.errorJsonResult(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get overdue bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return resultHandler.errorJsonResult(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get overdue bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return resultHandler.errorJsonResult(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get overdue bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return resultHandler.errorJsonResult(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get overdue bills error. Msg["+e.getMessage()+"]");
			return resultHandler.errorJsonResult(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	@RequestMapping(value = IReceivableDeferredPaymentDateBills.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivableDeferredPaymentDateBills.SUB_MENU_SETTING)
	public ModelAndView listDeferredPaymentDateBills(HttpServletRequest request,
										   @RequestParam(value = IReceivableDeferredPaymentDateBills.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
										   Page page, @Secure Principal principal) {
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<AuthorisedBillSketch>  overPaymentDateBills = receivableHandler.getOverPaymentDateBills(appId, particalUniqueId, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.overPaymentDateViewSpec(overPaymentDateBills, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get overdue bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get overdue bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get overdue bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get overdue bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get overdue bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	@RequestMapping(value = IReceivableNotReachPaymentDateBills.NAME,method = RequestMethod.GET)
	@MenuSetting(IReceivableNotReachPaymentDateBills.SUB_MENU_SETTING)
	public ModelAndView listNotReachPaymentDateBills(HttpServletRequest request,
										   @RequestParam(value = IReceivableNotReachPaymentDateBills.PARAM_UNIQUE_PARTICLE_ID,required = false,defaultValue = "")String particalUniqueId,
										   Page page, @Secure Principal principal) {
		try {
			
			ViewEntry viewCategory = getAuthorisedViewCategory(request, principal);
			
			String appId = viewCategory.getAppId();
			
			particalUniqueId = getFirstShowParticleUniqueId(particalUniqueId, viewCategory);
			
			ReceivableHandler receivableHandler = getReceivableHandler(viewCategory);
			if (receivableHandler == null){
				throw new NoReceivableHandlerException();
			}
			
			List<AuthorisedBillSketch>  notReachPaymentDateBills = receivableHandler.getNotReachPaymentDateBills(appId, particalUniqueId, page);
			
			List<AppParticles> quarkParticles = appParticlesService.getQuarkPartical(appId);
			
			return viewSpecHandler.notReachPaymentDateViewSpec(notReachPaymentDateBills, quarkParticles, createPrePageContext(request));
		
		}catch(NoReceivableHandlerException e){
			logger.error("get not due bills error. Null ReceivableHandler, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}catch(NoPaymentResourceException e){
			logger.error("get not due bills error. NoPaymentResourceException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch(InvalidViewCategoryException e){
			logger.error("get not due bills error. InvalidViewCategory Exception. errorcCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (NoAuthorityException e){
			logger.error("get not due bills error. NoAuthorityException, errorCode["+e.getErrorCode()+"], msg["+e.getErrorMsg()+"].");
			return viewSpecHandler.errorSpec(e.getErrorMsg());
		}catch (Exception e) {
			logger.error("get not due bills error. Msg["+e.getMessage()+"]");
			return viewSpecHandler.errorSpec(GlobalMsgSpec.GeneralErrorMsg.MSG_SYSTEM_BUSY);
		}
	}
	private ViewEntry getAuthorisedViewCategory(HttpServletRequest request, Principal principal) throws CommonException,NoAuthorityException, InvalidViewCategoryException{
		
		
		ViewEntry viewEntry=cookieHandler.getViewCategoryFromCookie(GlobalSpec4Earth.PARAM_VIEW_CATEGORY, request);
		
		if(null == viewEntry){
			
			throw new InvalidViewCategoryException(GlobalCodeSpec.GeneralErrorCode.ERROR_JSON_PARSE_NULL,GlobalMsgSpec.GeneralErrorMsg.MSG_NO_VIEW_ENTRY);
		}
		
		principal.isAuthorisedBy(viewEntry.getRole());
			
		return viewEntry;
	}
	private String createPrePageContext(HttpServletRequest request) {
		
		String queryString = request.getQueryString();
		
		if(!StringUtils.isEmpty(queryString)){
			
			Map<String, String> queries = com.demo2do.core.utils.StringUtils.parseQueryString(queryString);
			if (queries.containsKey(GlobalSpec4Earth.PARAM_PAGE)) {
				queries.remove(GlobalSpec4Earth.PARAM_PAGE);
			}
			return com.demo2do.core.utils.StringUtils.toQueryString(queries);
		}
		return org.apache.commons.lang.StringUtils.EMPTY;
	}
	private String getFirstShowParticleUniqueId(String particalUniqueId, ViewEntry viewCategory) throws NoPaymentResourceException {
		
		if(!StringUtils.isEmpty(particalUniqueId)){
			return particalUniqueId;
		}
			
		List<String> particalUniqueIds = appParticlesService.getQuarkParticalUniqueIds(viewCategory.getAppId());
		
		if(CollectionUtils.isNotEmpty(particalUniqueIds)){
			return particalUniqueIds.get(0);
		}
		
		if (!RoleSpec.ROLE_MERCURY_APP.equals(viewCategory.getRole())){
			throw new NoPaymentResourceException(GlobalCodeSpec.GeneralErrorCode.ERROR_NO_RESOURCE,GlobalMsgSpec.GeneralErrorMsg.MSG_NO_PAYMENT_RESOURCE);
		}
		return particalUniqueId;
	}
	private ReceivableHandler getReceivableHandler(ViewEntry viewEntry){
		
		switch(viewEntry.getRole()){
		
		case  RoleSpec.ROLE_MERCURY_APP :
			
			 return mercuryReceivableHandler;
			 
		default:
			
			return quarkReceivableHandler;
			
		}
	}
}
